package com.hy.service.impl;

import cn.hutool.core.convert.Convert;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.hy.common.base.RespResult;
import com.hy.common.base.RespResultCode;
import com.hy.common.consts.CommonConst;
import com.hy.common.excel.HyDepartmentImport;
import com.hy.common.excel.HyPropertyPlaceImport;
import com.hy.common.exception.ImportException;
import com.hy.common.utils.CommonUtils;
import com.hy.common.utils.ExcelUtil;
import com.hy.entity.dto.DepartmentSearchDTO;
import com.hy.entity.pojo.*;
import com.hy.entity.vo.*;
import com.hy.mapper.*;
import com.hy.service.HyDepartmentService;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.test.context.jdbc.Sql;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.sql.Timestamp;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Optional;

@Slf4j
@Service
public class HyDepartmentServiceImpl implements HyDepartmentService {

    @Resource
    private SqlSessionFactory sqlSessionFactory;

    @Resource
    private HyDepartmentMapper departmentMapper;
    @Resource
    private HyUserMapper hyUserMapper;
    @Resource
    private HyPropertyMapper  hyPropertyMapper;
    @Resource
    private HyUnitMapper unitMapper;

    @Resource
    private HyPlaceMapper  hyPlaceMapper;
    private Authentication authentication;
    @Override
    public RespResult addDepartment(HyDepartment department) {
        department.setDel(1);
        authentication= SecurityContextHolder.getContext().getAuthentication();
        HyUserVO hyUserVO= (HyUserVO) authentication.getPrincipal();
        List<String> roleIds = hyUserVO.getRoles();
        department.setCreateDate(CommonUtils.getDate());
        if (department.getManagerId()==null){
            department.setManagerId(CommonConst.DEFAULT_ID);
        }
        if (CommonUtils.isMember(roleIds,CommonConst.SYSTEM_ROLE_NAME)){

            departmentMapper.insert(department);
        }else {

            department.setUnitId(hyUserVO.getUnitId());
            departmentMapper.insert(department);
        }

        return RespResult.getInstance(RespResultCode.Add_SUCCESS);



    }

    public boolean isChecked(List<Integer> ids){
        authentication= SecurityContextHolder.getContext().getAuthentication();
        HyUserVO hyUserVO= (HyUserVO) authentication.getPrincipal();
        for(Integer id:ids){
            HyDepartment department = departmentMapper.selectById(id);
            if (department.getUnitId()!=hyUserVO.getUnitId()){
                return false;
            }
        }
        return true;

    }
    @Transactional(rollbackFor = Exception.class)
    @Override
    public RespResult deleteDepartment(List<Integer> ids) {
        authentication= SecurityContextHolder.getContext().getAuthentication();
        HyUserVO hyUserVO= (HyUserVO) authentication.getPrincipal();
        List<String> roleIds = hyUserVO.getRoles();
        if (CommonUtils.isMember(roleIds,CommonConst.SYSTEM_ROLE_NAME)){
            departmentMapper.deleteBatchIds(ids);
            ids.forEach(e->{
                //1、将用户的部门设置为暂无部门
                LambdaQueryWrapper<HyUser> hyUserLambdaQueryWrapper=new LambdaQueryWrapper<>();
                hyUserLambdaQueryWrapper.eq(HyUser::getDepartmentId,e);
                List<HyUser> hyUsers = hyUserMapper.selectList(hyUserLambdaQueryWrapper);
                Optional.ofNullable(hyUsers)
                        .filter(p->
                            !Integer.valueOf(p.size()).equals(0)
                        )
                        .ifPresent(users ->{
                            LambdaUpdateWrapper<HyUser> hyUserLambdaUpdateWrapper=new LambdaUpdateWrapper<>();
                            hyUserLambdaUpdateWrapper.set(HyUser::getDepartmentId,CommonConst.DEFAULT_ID).in(HyUser::getUserId,users.stream().map(HyUser::getUserId).toArray());
                            hyUserMapper.update(null,hyUserLambdaUpdateWrapper);

                        });
                //2、将资产的管理部门、使用部门设置成暂无
                LambdaQueryWrapper<HyProperty> hyPropertyLambdaQueryWrapper=new LambdaQueryWrapper<>();
                hyPropertyLambdaQueryWrapper.eq(HyProperty::getOwnerDeptId,e).or().eq(HyProperty::getManagerDeptId,e);
                List<HyProperty> hyProperties = hyPropertyMapper.selectList(hyPropertyLambdaQueryWrapper);
                Optional.ofNullable(hyProperties)
                        .filter(p->
                                !Integer.valueOf(p.size()).equals(0)
                        )
                        .ifPresent(property->
                            property.forEach(p->{
                                if (p.getOwnerDeptId().equals(e)){
                                    HyProperty hyProperty=new HyProperty();
                                    hyProperty.setPropertyId(p.getPropertyId());
                                    hyProperty.setOwnerDeptId(CommonConst.DEFAULT_ID);
                                    hyPropertyMapper.updateById(hyProperty);
                                }
                                if (p.getManagerDeptId().equals(e)){
                                    HyProperty hyProperty=new HyProperty();
                                    hyProperty.setPropertyId(p.getPropertyId());
                                    hyProperty.setManagerDeptId(CommonConst.DEFAULT_ID);
                                    hyPropertyMapper.updateById(hyProperty);
                                }
                            })
);
                //3、将区域的所属部门设置未暂无
                LambdaQueryWrapper<HyPlace> placeLambdaQueryWrapper=new LambdaQueryWrapper<>();
                placeLambdaQueryWrapper.eq(HyPlace::getOwnerDeptId,e);
                List<HyPlace> places = hyPlaceMapper.selectList(placeLambdaQueryWrapper);
                Optional.ofNullable(places)
                        .filter(p->
                                !Integer.valueOf(p.size()).equals(0)
                        )
                        .ifPresent(p->{
                            LambdaUpdateWrapper<HyPlace> placeLambdaUpdateWrapper=new LambdaUpdateWrapper<>();
                            placeLambdaUpdateWrapper.set(HyPlace::getOwnerDeptId,CommonConst.DEFAULT_ID).in(HyPlace::getPlaceId,p.stream().map(HyPlace::getPlaceId).toArray());
                            hyPlaceMapper.update(null,placeLambdaUpdateWrapper);
                        });
            });
        }else {
            if (isChecked(ids)){
                departmentMapper.deleteBatchIds(ids);
            }else {
                return RespResult.error(500,"不能删除非本单位的部门！");
            }
        }

        return RespResult.getInstance(RespResultCode.DEL_SUCCESS);
    }

    @Override
    public RespResult showDepartment(DepartmentSearchDTO searchDTO) {
        searchDTO.setDel(1);
        authentication= SecurityContextHolder.getContext().getAuthentication();
        HyUserVO hyUserVO= (HyUserVO) authentication.getPrincipal();
        List<String> roleIds = hyUserVO.getRoles();
        List<HyDepartmentVO> hyDepartmentVOS;
        Page<HyDepartment> page=new Page<>(searchDTO.getCurrentPage(),searchDTO.getPageSize());
        if (CommonUtils.isMember(roleIds,CommonConst.SYSTEM_ROLE_NAME)){

            hyDepartmentVOS=  departmentMapper.showDepartmentsByDto(page,searchDTO);
        }else {

            searchDTO.setUnitId(hyUserVO.getUnitId());
            hyDepartmentVOS=departmentMapper.showDepartmentsByDto(page,searchDTO);
        }
        return RespResult.success(hyDepartmentVOS)
                .setCount(Long.valueOf(page.getTotal()).intValue());
    }

    @Override
    public RespResult updateDepartment(HyDepartment department) {

        authentication= SecurityContextHolder.getContext().getAuthentication();
        HyUserVO hyUserVO= (HyUserVO) authentication.getPrincipal();
        List<String> roleIds = hyUserVO.getRoles();
        if (CommonUtils.isMember(roleIds,CommonConst.SYSTEM_ROLE_NAME)){

            departmentMapper.updateById(department);
        }else {

            department.setUnitId(hyUserVO.getUnitId());
            departmentMapper.updateById(department);
        }
        return RespResult.getInstance(RespResultCode.UPDATE_SUCCESS);
    }

    @Override
    public RespResult getCanHandleDept() {

        authentication= SecurityContextHolder.getContext().getAuthentication();
        HyUserVO hyUserVO= (HyUserVO) authentication.getPrincipal();
        List<String> roleIds = hyUserVO.getRoles();
        List<HyDepartmentVO> hyDepartmentVOS;
        if (CommonUtils.isMember(roleIds,CommonConst.SYSTEM_ROLE_NAME)){

            hyDepartmentVOS=  departmentMapper.showDept(new DepartmentSearchDTO());
        }else {
            DepartmentSearchDTO departmentSearchDTO = new DepartmentSearchDTO();
            departmentSearchDTO.setUnitId(hyUserVO.getUnitId());
            hyDepartmentVOS=departmentMapper.showDept(departmentSearchDTO);
        }
        HyDepartmentVO department=new HyDepartmentVO();
        department.setDepartmentId(CommonConst.DEFAULT_ID);
        department.setDepartmentName("暂无");
        hyDepartmentVOS.add(department);


        return RespResult.success(hyDepartmentVOS);
    }

    @Override
    public List<HyDepartmentVO> listPage(Map<String, Object> queryCondition, Integer pageNo, Integer pageSize) {
        Integer offset = (pageNo - 1) * pageSize;
        Integer rows = pageSize;
        authentication= SecurityContextHolder.getContext().getAuthentication();
        HyUserVO principal = (HyUserVO) authentication.getPrincipal();
        List<String> roles = principal.getRoles();
        queryCondition.put("offset",offset);
        queryCondition.put("rows",rows);
        List<HyDepartmentVO> departmentVOS=null;
        if(CommonUtils.isMember(roles, CommonConst.SYSTEM_ROLE_NAME)){

            departmentVOS= departmentMapper.findHyPropertyListByMap(queryCondition);
        }else {
            queryCondition.put("unitId",principal.getUnitId());
            departmentVOS=departmentMapper.findHyPropertyListByMap(queryCondition);
        }
        return departmentVOS;
    }

    @Override
    public void saveStuListWithBatch(List<HyDepartment> data) {
        /**
         * mybatis提供三种sql执行器，分别是SIMPLE（默认）、REUSE、BATCH
         * SIMPLE	默认执行器， 节约服务器资源	每次都要开关Statement
         * REUSE	提升后端接口处理效率	每次一个新sql都缓存，增大JVM内存压力
         * BATCH	专门用于更新插入操作，效率最快	对select 不适用，另外特殊要求，比如限制一次execteBatch的数量时需要写过滤器定制
         */
        // 打开批处理
        SqlSession session = sqlSessionFactory.openSession(ExecutorType.BATCH);
        /*HyPropertyBatchMapper empBatchMapper = session.getMapper(HyPropertyBatchMapper.class);*/
        for (int i = 0,length = data.size(); i < length; i++) {
            HyDepartment place = data.get(i);
            UserRoleConn conn=new UserRoleConn();
            departmentMapper.insert(place);
//            empBatchMapper.insert(data.get(i));
            //每1000条提交一次防止内存溢出
            if(i % 10000==9999){
                session.commit();
                session.clearCache();
            }
        }
        session.commit();
        session.clearCache();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public RespResult importExcelBigData(MultipartFile multipartFile, HttpServletRequest request) {
        RespResult r = RespResult.success();

        try{
            long start = System.currentTimeMillis();
            HyDepartmentImport departmentImport=new HyDepartmentImport(departmentMapper,unitMapper,this,hyUserMapper);
            Integer sheetNo = Convert.toInt(request.getParameter("sheetNo"), 0);
            ExcelUtil.readExcel(multipartFile.getInputStream(), HyDepartmentReadVO.class,
                    departmentImport, sheetNo);
            log.info("本次导入100w数据，总耗时:{}ms", (System.currentTimeMillis() -start));
            r.setCode(200);
            r.setMessage("导入成功");
            return r;
        } catch (Exception e){
            log.error(e.getMessage(), e);
            throw new ImportException(e.getMessage());
        }

    }
}
